perm filename CATCH.RPG[3,2] blob
sn#553408 filedate 1981-01-03 generic text, type C, neo UTF8
COMMENT ā VALID 00002 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 New Catch/Throw Functions
C00008 ENDMK
Cā;
New Catch/Throw Functions
The next release of MacLisp at SAIL will use the *catch/*throw
protocol; it is suggested that you convert your functions
as soon as possible. You may want to macro-ize things for now
rather than actually editting the changes in. [rpg;2-jan-81]
*THROW, *CATCH, CATCHALL, CATCH-BARRIER, and UNWIND-PROTECT.
For compatibility with the new format of CATCH and THROW in the
LISP Machine, and in NIL, we are introducing *THROW and *CATCH.
Please use these, and sometime in the future, CATCH and THROW in
PDP10 MACLISP may be changed also. It is recommended that old code be
converted to *CATCH and *THROW.
(*CATCH <tag> e1 e2 ... e<n>)
Forms e1 through e<n> are evaluated, returning the last as the
value of the CATCH, unless a THROW (or *THROW) occurs whose tag matches
the value of <tag> during the sub-evaluations; then the value of
the catch is the value from the THROW. Note that <tag> is evaluated
first.
(*THROW <tag> <val>)
Both <tag> and <val> are evaluated as in normal SUBR control,
and a control-chain break-up is initiated, passing along both
values; at some higher level, the break-up will be "caught".
If the "catching" is by CATCH, then the value of <val> is
passed to CATCH; if by CATCHALL, the both values are passed (q.v.).
(CATCHALL <fun-2-args> e1 e2 ... e<n>)
Has same semantics as CATCH, except that if **any** THROW occurs
during the sub-evaluations, then the value of the CATCH is obtained
by applying the value of <fun-2-args> to the throw value and throw
tag. E.g.
(CATCHALL '(LAMBDA (TG VAL)
;Note that for some tags, the throw is
; repeated, so that the CATCHALL acts as
; if it in fact ignores that THROW.
(COND ((MEMQ TG '(TOPLEVEL BREAK)) (THROW VAL TG))
((OR STOPP (EQ TG 'FOO)) (THROW VAL 'FOO))
(#T VAL)))
(SETUP 25)
(RUNLIKE ABAT))
(CATCH-BARRIER <tag-list> e1 e2 ... e<n>)
Has the same syntax as CATCH, and more or less the same semantics, but
if a thrown tag is not in the tag-list, then the THROW that threw it
goes into an unseen-throw-tag error. The idea is that searching does
not proceed back up the stack beyond this point; whereas if a THROW of
a tag is not caught by a particular CATCH, then tag searching continues
back up to the stack above the CATCH.
(UNWIND-PROTECT <e> u1 u2 ... u<n>)
The form <e> will be evaluated, but if the stack is "unwound" past
the point of the UNWIND-PROTECT for ANY REASON,
then the unwinder must cause the evaluation, in order,
of u1 through u<n> in the environment that obtains by first
unwinding to the stack point of the UNWIND-PROTECT; then the
unwinding may continue. If <e> terminates normally, then
the value will be that obtained from <e>, but the forms u1
through u<n> will be evaluated also. The intent is
that the operation of <e> will do some things that need to be
undone after sucessful completion, but which can not be undone
merely by lambda-binding (eg, closing an opened file). Thus any
aborting of the evaluation of <e> will not leave undesired states
hanging around. Before the u<n>'s are run, NOINTERRUPT is set to
T, so that asynchronous conditions cannot cause premature termination
of the handlers. It is restored to its previous value upon
completion of the u<n>'s. If a THROW is done, the user must reset
NOINTERRUPT to the value he wishes it to be! The UNWIND-PROTECT
frame is removed from the stack BEFORE the u<n>'s are run so that
they may freely do THROWS (et al.).